from flask import Flask, render_template, request, redirect, url_for, flash, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from PIL import Image
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///antiques.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024  # 500MB max file size
app.config['MAX_CONTENT_LENGTH_PER_FILE'] = 50 * 1024 * 1024  # 50MB per file

# Ensure upload directory exists
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

# 初始化数据库
db = SQLAlchemy(app)
migrate = Migrate(app, db)

# 初始化登录管理器
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# Models
class User(UserMixin, db.Model):
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(120), nullable=False)
    created_at = db.Column(db.DateTime, server_default=db.func.now())
    updated_at = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now())

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

class Antique(db.Model):
    __tablename__ = 'antiques'
    
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text)
    era = db.Column(db.String(50))  # 年代
    dimensions = db.Column(db.String(100))  # 尺寸
    price = db.Column(db.String(50))  # 优惠价
    main_image = db.Column(db.String(200))
    sort_order = db.Column(db.Integer, default=0)  # 排序字段
    created_at = db.Column(db.DateTime, server_default=db.func.now())
    updated_at = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now())
    
    # 关系
    images = db.relationship('AntiqueImage', backref='antique', lazy=True, cascade='all, delete-orphan')

class AntiqueImage(db.Model):
    __tablename__ = 'antique_images'
    
    id = db.Column(db.Integer, primary_key=True)
    antique_id = db.Column(db.Integer, db.ForeignKey('antiques.id'), nullable=False)
    image_path = db.Column(db.String(200), nullable=False)
    thumbnail_path = db.Column(db.String(200), nullable=False)
    is_main = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, server_default=db.func.now())
    updated_at = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now())

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

def compress_image(image_path, max_size=(800, 800)):
    img = Image.open(image_path)
    img.thumbnail(max_size)
    img.save(image_path, optimize=True, quality=85)

def create_thumbnail(image_path, thumbnail_path, size=(300, 300)):
    img = Image.open(image_path)
    img.thumbnail(size)
    img.save(thumbnail_path, optimize=True, quality=85)

# Routes
@app.route('/')
def index():
    antiques = Antique.query.order_by(Antique.sort_order.desc()).all()
    return render_template('index.html', antiques=antiques)

@app.route('/antique/<int:id>')
def antique_detail(id):
    antique = Antique.query.get_or_404(id)
    return render_template('detail.html', antique=antique)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter_by(username=username).first()
        
        if user and user.check_password(password):
            login_user(user)
            return redirect(url_for('admin_dashboard'))
        flash('Invalid username or password')
    return render_template('login.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))

@app.route('/admin')
@login_required
def admin_dashboard():
    antiques = Antique.query.all()
    return render_template('admin/dashboard.html', antiques=antiques)

@app.route('/admin/antique/new', methods=['GET', 'POST'])
@login_required
def new_antique():
    if request.method == 'POST':
        name = request.form.get('name')
        description = request.form.get('description')
        era = request.form.get('era')
        dimensions = request.form.get('dimensions')
        price = request.form.get('price')
        sort_order = request.form.get('sort_order', type=int) or 0
        files = request.files.getlist('images')
        
        antique = Antique(
            name=name,
            description=description,
            era=era,
            dimensions=dimensions,
            price=price,
            sort_order=sort_order
        )
        db.session.add(antique)
        db.session.flush()  # Get the antique ID
        
        # 处理图片上传
        for i, file in enumerate(files):
            if file and file.filename:
                try:
                    filename = secure_filename(file.filename)
                    filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
                    file.save(filepath)
                    compress_image(filepath)
                    
                    # Create thumbnail
                    thumbnail_filename = f"thumb_{filename}"
                    thumbnail_path = os.path.join(app.config['UPLOAD_FOLDER'], thumbnail_filename)
                    create_thumbnail(filepath, thumbnail_path)
                    
                    image = AntiqueImage(
                        antique_id=antique.id,
                        image_path=filename,
                        thumbnail_path=thumbnail_filename,
                        is_main=(i == 0)  # First image is main
                    )
                    db.session.add(image)
                    if i == 0:
                        antique.main_image = thumbnail_filename
                except Exception as e:
                    flash(f'图片 {file.filename} 上传失败: {str(e)}', 'error')
                    continue
        
        db.session.commit()
        return redirect(url_for('admin_dashboard'))
    
    return render_template('admin/new_antique.html')

@app.route('/admin/antique/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit_antique(id):
    antique = Antique.query.get_or_404(id)
    
    if request.method == 'POST':
        antique.name = request.form.get('name')
        antique.description = request.form.get('description')
        antique.era = request.form.get('era')
        antique.dimensions = request.form.get('dimensions')
        antique.price = request.form.get('price')
        antique.sort_order = request.form.get('sort_order', type=int) or 0
        
        # 处理新上传的图片
        files = request.files.getlist('images')
        if files and files[0].filename:
            for file in files:
                if file and file.filename:
                    try:
                        filename = secure_filename(file.filename)
                        filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
                        file.save(filepath)
                        compress_image(filepath)
                        
                        # Create thumbnail
                        thumbnail_filename = f"thumb_{filename}"
                        thumbnail_path = os.path.join(app.config['UPLOAD_FOLDER'], thumbnail_filename)
                        create_thumbnail(filepath, thumbnail_path)
                        
                        image = AntiqueImage(
                            antique_id=antique.id,
                            image_path=filename,
                            thumbnail_path=thumbnail_filename,
                            is_main=False  # 新上传的图片默认不是主图
                        )
                        db.session.add(image)
                    except Exception as e:
                        flash(f'图片 {file.filename} 上传失败: {str(e)}', 'error')
                        continue
        
        db.session.commit()
        return redirect(url_for('admin_dashboard'))
    
    return render_template('admin/edit_antique.html', antique=antique)

@app.route('/admin/antique/<int:id>/delete', methods=['POST'])
@login_required
def delete_antique(id):
    antique = Antique.query.get_or_404(id)
    
    # Delete image files
    for image in antique.images:
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], image.image_path))
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], image.thumbnail_path))
        except:
            pass
    
    db.session.delete(antique)
    db.session.commit()
    return jsonify({'success': True})

@app.route('/admin/antique/<int:antique_id>/image/<int:image_id>/delete', methods=['POST'])
@login_required
def delete_image(antique_id, image_id):
    try:
        image = AntiqueImage.query.get_or_404(image_id)
        if image.antique_id != antique_id:
            return jsonify({'success': False, 'message': '图片不属于该藏品'})
        
        # 删除文件
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], image.image_path))
        except:
            pass  # 如果文件不存在，继续执行
        
        try:
            os.remove(os.path.join(app.config['UPLOAD_FOLDER'], image.thumbnail_path))
        except:
            pass  # 如果文件不存在，继续执行
        
        # 如果删除的是主图，需要更新主图
        if image.is_main:
            antique = Antique.query.get(antique_id)
            other_image = AntiqueImage.query.filter(
                AntiqueImage.antique_id == antique_id,
                AntiqueImage.id != image_id
            ).first()
            
            if other_image:
                other_image.is_main = True
                antique.main_image = other_image.thumbnail_path
            else:
                antique.main_image = None
        
        db.session.delete(image)
        db.session.commit()
        return jsonify({'success': True})
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': str(e)})

@app.route('/admin/antique/<int:antique_id>/image/<int:image_id>/set-main', methods=['POST'])
@login_required
def set_main_image(antique_id, image_id):
    try:
        image = AntiqueImage.query.get_or_404(image_id)
        if image.antique_id != antique_id:
            return jsonify({'success': False, 'message': '图片不属于该藏品'})
        
        # 将当前主图设置为非主图
        current_main = AntiqueImage.query.filter_by(
            antique_id=antique_id,
            is_main=True
        ).first()
        if current_main:
            current_main.is_main = False
        
        # 设置新的主图
        image.is_main = True
        antique = Antique.query.get(antique_id)
        antique.main_image = image.thumbnail_path
        
        db.session.commit()
        return jsonify({'success': True})
    except Exception as e:
        db.session.rollback()
        return jsonify({'success': False, 'message': str(e)})

if __name__ == '__main__':
    with app.app_context():
        # 创建所有数据库表
        db.create_all()
        
        # 创建管理员用户（如果不存在）
        if not User.query.filter_by(username='admin').first():
            admin = User(username='admin')
            admin.set_password('admin1234')
            db.session.add(admin)
            db.session.commit()
    
    app.run(debug=True) 